package com.fdd.spring.annotation;

import org.springframework.stereotype.Component;
import org.springframework.stereotype.Controller;
import org.springframework.stereotype.Repository;
import org.springframework.stereotype.Service;

import java.io.File;
import java.lang.annotation.Annotation;
import java.net.URL;
import java.util.concurrent.ConcurrentHashMap;

public class HspSpringApplicationContext {
    private Class configClass;
    //通过反射创建的对象，基于注解的方式
    private final ConcurrentHashMap<String, Object> ioc = new ConcurrentHashMap<>();

    public HspSpringApplicationContext(Class configClass) {
        this.configClass = configClass;
        //解析配置类,得到它的注解和值
        Annotation annotation = this.configClass.getAnnotation(ComponentScan.class);
        if (annotation == null) {
            throw new RuntimeException("配置类缺少@ComponentScan注解");
        }
        //获取注解的值,也就是要扫描的包的路径
        String path = ((ComponentScan) annotation).value();
        //扫描path路径下的所有类，得到类的名字。注意要将包的路径转换成文件的路径
        URL resource = this.getClass().getClassLoader().getResource(path.replace(".", "/"));
        //获取下面的类名
        assert resource != null;
        File file = new File(resource.getPath());
        for (File f : file.listFiles()) {

            if (f.getPath().endsWith(".class")) {

                //得到类名
                String className = path + "." + f.getName().replace(".class", "");
//                System.out.println(className);
                //反射创建对象
            try {
                Class<?> aClass = Class.forName(className);
                //判断是否是组件类
                if (aClass.isAnnotationPresent(Component.class)||
                        aClass.isAnnotationPresent(Service.class) ||
                aClass.isAnnotationPresent(Controller.class) ||
                        aClass.isAnnotationPresent(Repository.class)) {
                    //是组件类，就放到ioc容器中
                    String beanName = aClass.getSimpleName().substring(0, 1).toLowerCase() + aClass.getSimpleName().substring(1);
                    ioc.put(beanName, aClass.newInstance());
                }
            } catch (Exception e) {
                throw new RuntimeException();
            }


            }
        }
    }

    public Object getBean(String beanName) {
        return ioc.get(beanName);
    }
}
